package db

import (
	"database/sql"
	"log"
	"os"
	"strings"
	"text/template"
)

const (
	driverName     = "mysql"

	tableSql  = "select table_name as name, table_comment as comment from information_schema.tables where table_schema=?"
	columnSql = "select is_nullable as empty, column_default as defaultValue, column_name as name, column_comment as comment, column_type as category from information_schema.columns where table_name=? and table_schema = ?"
	dbName    = "eatfun_takeout"

	templateContent = `
{{ range $i, $t := . }}

-  {{$t.Name}}, {{$t.Comment.String}}

|字段|类型|空|默认|注释|
|:----    |:-------  |:--- |---|------|
{{ range $j, $f := $t.Fields }}|{{$f.Name}} |{{$f.Category}} |{{$f.Empty.String}} | {{$f.DefaultValue.String}} | {{$f.Comment.String}} |
{{ end }}
{{ end }}`
)

// 定义一个成员变量保存
var db *sql.DB
var DataSourceName string

// 数据库字段
type Field struct {
	Name         string // name 字段名称
	Category     string // category 字符类型+长度
	Empty        sql.NullString // empty 是否为空
	DefaultValue sql.NullString // defaultValue 默认值
	Comment      sql.NullString // comment 注释
}

// 数据库表
type Table struct {
	Name    string
	Comment sql.NullString
	Fields  []Field
}

// 取得db, 如果异常返回nil
func getDB() *sql.DB {
	if db != nil {
		return db
	}
	dbb, err := sql.Open(driverName, DataSourceName)
	if err == nil {
		db = dbb
		return db
	}
	panic(err)
}

// 取得表对应的字段信息
func getField(tbName string) []Field {
	rows, err := getDB().Query(columnSql, tbName, dbName)
	if err != nil {
		panic(err)
	}
	var fields []Field
	for rows.Next() {
		var field Field
		if err := rows.Scan(&field.Empty, &field.DefaultValue, &field.Name, &field.Comment, &field.Category); err == nil {
			// 删除换行符
			field.Comment.String = strings.Replace(field.Comment.String, "\n", "", -1)
			fields = append(fields, field)
			log.Printf("field[empty=%s, defaultValue=%s, name=%s, comment=%s, category=%s]", field.Empty.String, field.DefaultValue.String, field.Name, field.Comment.String, field.Category)
		} else {
			panic(err)
		}
	}
	return fields
}

// 取得所有的表信息
func getTables() []Table {
	rows, err := getDB().Query(tableSql, dbName)
	if err != nil {
		panic(err)
	}

	var tables []Table
	for rows.Next() {
		var table Table
		if err := rows.Scan(&table.Name, &table.Comment); err == nil {
			table.Fields = getField(table.Name)
			tables = append(tables, table)
			log.Printf("table[name=%s, comment=%s]", table.Name, table.Comment.String)
		}
	}
	return tables
}

// 创建数据库字典
func CreateDictionary(dictionary string) {
	defer getDB().Close()
	// 创建字典文件
	f, err := os.Create(dictionary)
	if err != nil {
		panic("文件[" + dictionary + "]创建失败")
	}
	// 创建模板
	t := template.Must(template.New("letter").Parse(templateContent))

	tables := getTables()

	err = t.Execute(f, tables)
	if err != nil {
		log.Println("执行模板引擎失败:", err)
	}
}
